# -*- Mode: Python -*- vi:si:et:sw=4:sts=4:ts=4:syntax=python
from cerbero.tools.libtool import LibtoolLibrary

class Recipe(recipe.Recipe):
    name = 'ffmpeg'
    version = '4.2'
    licenses = [License.LGPLv2_1Plus]
    stype = SourceType.TARBALL
    url = 'https://ffmpeg.org/releases/%(name)s-%(version)s.tar.bz2'
    tarball_checksum = '306bde5f411e9ee04352d1d3de41bd3de986e42e2af2a4c44052dce1ada26fb8'
    patches = []

    btype = BuildType.MAKEFILE
    configure_tpl = './configure --prefix=%(prefix)s --libdir=%(libdir)s \
        --ar="$AR" --as="$CC" --cc="$CC" --ld="$CC" --nm="$NM" --ranlib="$RANLIB" \
        --strip="$STRIP" --windres="$RC" \
        --enable-static --enable-pic --enable-shared \
        --disable-avdevice --disable-postproc --disable-swscale \
        --disable-programs --disable-ffplay --disable-ffprobe --disable-ffmpeg \
        --disable-encoder=flac --disable-protocols --disable-devices \
        --disable-network --disable-hwaccels --disable-dxva2 --disable-vdpau \
        --disable-filters --enable-filter=yadif --disable-doc --disable-d3d11va \
        --disable-audiotoolbox --disable-videotoolbox --disable-vaapi --disable-crystalhd \
        --disable-mediacodec --disable-nvenc --disable-mmal --disable-omx \
        --disable-omx-rpi --disable-cuda --disable-cuvid --disable-libmfx \
        --disable-libnpp --disable-iconv --disable-jni --disable-v4l2_m2m \
        --enable-optimizations --disable-nonfree --disable-version3 %(options)s'

    deps = ['bzip2', 'zlib']

    files_libs = ['libavcodec', 'libavformat', 'libavutil', 'libswresample', 'libavfilter']
    files_devel = []

    def prepare(self):
        # Populate self.files_devel
        files_devel_tpl = ['lib/{}.la', 'lib/pkgconfig/{}.pc', 'include/{}']
        # ffmpeg can only build either shared or static on Windows, not both
        if self.config.target_platform == Platform.WINDOWS:
            self.library_type = LibraryType.SHARED
        else:
            files_devel_tpl += ['lib/{}.a']
        for lib in self.files_libs:
            self.files_devel += [tpl.format(lib) for tpl in files_devel_tpl]

        # Default AS is $CC, except iOS (set below)
        if Architecture.is_arm(self.config.target_arch):
            if self.config.target_platform == Platform.IOS:
                gas = self.get_env('GAS')
                if gas:
                    self.set_env('AS', gas)
            else:
                self.set_env('AS', self.get_env('CC'))

        libavextraconf = ''
        # Arch-specific flags
        if self.config.target_platform == Platform.ANDROID:
            if self.config.target_arch == Architecture.X86:
              # libav internally aligns stacks, while Android doesn't
                libavextraconf += " --extra-cflags='-mstackrealign'"
            if self.config.target_arch in [Architecture.X86]:
                # Fails to link into an android app with relocation warnings
                # in the custom assembly
                # https://stackoverflow.com/questions/34691970/ffmpeg-for-android-neon-build-has-text-relocations/34697703#34697703
                # https://issuetracker.google.com/issues/37067983
                # https://trac.ffmpeg.org/ticket/4928
                libavextraconf += " --disable-asm"
        elif self.config.target_platform == Platform.IOS:
            # Some optimisations that were previously silently disabled
            # cause warnings now. Ignore them
            libavextraconf += " --extra-cflags='-Wno-ignored-optimization-argument' "
            if self.config.target_arch == Architecture.X86:
                # Fails to link in gst-libav due to text relocations in
                # custom assembly:
                # ld: illegal text-relocation to 'anon' in libavfilter.a(vf_yadif.o)
                # from '_ff_yadif_filter_line_ssse3' in libavfilter.a(vf_yadif.o)
                # for architecture i386
                libavextraconf += ' --disable-asm  '

        # On windows, being a multilib toolchain, we have to always configure
        # the cross-prefix
        if self.config.cross_compiling() or \
                self.config.target_platform == Platform.WINDOWS:
            libavextraconf += ' --enable-cross-compile'
            target_os = self.config.target_platform
            if target_os == 'windows':
                target_os = 'mingw32'
            elif target_os == 'ios':
                target_os = 'darwin'
            target_arch = self.config.host.split('-', 1)[0]
            libavextraconf += ' --target-os=' + target_os
            libavextraconf += ' --arch=' + target_arch
            libavextraconf += ' --cross-prefix={} '\
                    .format(self.config.tools_prefix or self.config.host)

        self.configure_options += libavextraconf
        # On Windows, make fails if V=1 is passed with:
        # `couldn't commit memory for cygwin heap, Win32 error 0`
        if self.config.platform == Platform.WINDOWS:
            self.make = ['make']

    async def configure(self):
        await super(recipe.Recipe, self).configure()
        libav_path = self.build_dir
        if self.config.target_platform in [Platform.DARWIN, Platform.IOS]:
            if self.config.target_arch == Architecture.X86:
                replacements = {'HAVE_EBX_AVAILABLE=yes': 'HAVE_EBX_AVAILABLE=no',
                                'HAVE_EBX_AVAILABLE 1': 'HAVE_EBX_AVAILABLE 0',}
                shell.replace(os.path.join(libav_path, 'ffbuild', 'config.mak'), replacements)
                shell.replace(os.path.join(libav_path, 'config.h'), replacements)
        # log2 and log2f are not provided by bionic, but they are not checked
        # properly
        elif self.config.target_platform == Platform.ANDROID:
                replacements = {'HAVE_LOG2 1': 'HAVE_LOG2 0',
                                'HAVE_LOG2F 1': 'HAVE_LOG2F 0',}
                shell.replace(os.path.join(libav_path, 'config.h'), replacements)

                v = DistroVersion.get_android_api_version(self.config.target_distro_version)
                if self.config.target_arch in [Architecture.ARM, Architecture.ARMv7, Architecture.X86] and v < 21:
                        replacements = {'-D_FILE_OFFSET_BITS=64': '',}
                        shell.replace(os.path.join(libav_path, 'ffbuild', 'config.mak'), replacements)

    def post_install(self):
        LibtoolLibrary('avutil', None, None, None,
                       self.config.libdir, self.config.target_platform).save()
        LibtoolLibrary('swresample', None, None, None,
                       self.config.libdir, self.config.target_platform,
                       deps=['avutil']).save()
        LibtoolLibrary('avcodec', None, None, None,
                       self.config.libdir, self.config.target_platform,
                       deps=['swresample', 'avutil', 'z']).save()
        LibtoolLibrary('avformat', None, None, None,
                       self.config.libdir, self.config.target_platform,
                       deps=['avcodec', 'swresample', 'avutil', 'bz2', 'z']).save()
        LibtoolLibrary('avfilter', None, None, None,
                       self.config.libdir, self.config.target_platform,
                       deps=['avformat', 'avcodec', 'swresample', 'avutil']).save()
        super().post_install()
